

#include <asset/reader/assetreaderlevelofdetailsolver.h>
#include <ifile.h>
#include <fs/fileinfo.h>
#include <gfx/levelofdetail.h>
#include <vfs.h>
#include <cffformat.h>

ceAssetReaderLevelOfDetailSolver::ceAssetReaderLevelOfDetailSolver()
{
  CE_OBJECT_CONSTR
}

bool ceAssetReaderLevelOfDetailSolver::CanRead(ceEngine *engine, ceAssetTypeID type, const ceAssetLocator &locator)
{
  if (type != iLevelOfDetailSolver::AssetTypeID)
    {
      return false;
    }

  ceFileInfo info (locator.GetLocation());
  std::string ext = info.GetExtension();
  return ext == "slv";
}


ceRef<ceAsset> ceAssetReaderLevelOfDetailSolver::Read(ceEngine *engine, ceAssetTypeID type, const ceAssetLocator &locator)
{
  ceReleasePtr<iFile> file (ceVFS::Get()->Open(locator.GetLocation()));
  if (!file)
    {
      return 0;
    }
  long size = file->GetLength();

  char* buffer = new char[size+1];
  file->Read(buffer, size);
  file->Close ();

  buffer[size] = '\0';

  cffParser parser;
  ceReleasePtr<cffNode> parent (parser.ParseFromBuffer(buffer));
  delete [] buffer;
  if (!parent)
    {
      return 0;
    }

  cffNode *solverNode = FindNode(parent, locator.GetName());
  if (!solverNode)
    {
      return 0;
    }

  if (!solverNode->HasNamedAttribute("type"))
    {
      return 0;
    }

  iLevelOfDetailSolver* solver = 0;
  std::string solverType (solverNode->GetNamedAttribute("type"));
  if (solverType == std::string ("linear"))
    {
      cffNode* bestNode = solverNode->GetNode("best");
      cffNode* worstNode = solverNode->GetNode("worst");
      cffNode *getLastNode = solverNode->GetNode("getlast");


      float min = 0;
      float max = 1;
      bool getLast = true;
      if (bestNode && bestNode->HasAttribute(0))
        {
          min = bestNode->GetAttribute(0).AsFloat();
        }
      if (worstNode && worstNode->HasAttribute(0))
        {
          max = worstNode->GetAttribute(0).AsFloat();
        }
      if (getLastNode && getLastNode->HasAttribute(0))
        {
          getLast = std::string("true") == std::string (getLastNode->GetAttribute(0));
        }

      solver = new ceLinearLevelOfDetailSolver(min, max, getLast);
    }



  return solver;
}




cffNode* ceAssetReaderLevelOfDetailSolver::FindNode(cffNode *parent, const char *name)
{
  for (unsigned i=0, j=parent->GetNumberOfNodes(); i<j; ++i)
    {
      cffNode* solverNode = parent->GetNode(i);
      if (solverNode
          && solverNode->GetName() == std::string("solver")
          && solverNode->HasAttribute(0)
          && std::string (name) == (const char*)solverNode->GetAttribute(0))
        {
          return solverNode;
        }

    }

  return 0;
}

